﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using Dsl.Ped.Common;
using Dsl.Ped.Framework.Messages;
using System.Linq;
using GalaSoft.MvvmLight.Messaging;

namespace Dsl.Ped.Desktop.Modules.ErrorViewer
{
    /// <summary>
    /// View model of the <see cref="ErrorViewerView"/> class
    /// </summary>
    public class ErrorViewerViewModel : ViewModelBase
    {
        #region Fields

        /// <summary>
        /// Indicates if the Info messages should be displayed
        /// </summary>
        private bool isInfoSelected = true;

        /// <summary>
        /// Indicates if the Warning messages should be displayed
        /// </summary>
        private bool isWarningsSelected = true;

        /// <summary>
        /// Indicates if the Error messages should be displayed
        /// </summary>
        private bool isErrorsSelected = true;

        /// <summary>
        /// All messages to be displayed using a module
        /// </summary>
        private IEnumerable<NotifyMessage> messages;

        #endregion

        #region Constructors

        /// <summary>
        /// Initializes a new instance of the <see cref="ErrorViewerViewModel"/> class. 
        /// </summary>
        public ErrorViewerViewModel()
        {
            // Clear the collection of messages
            messages = new ObservableCollection<NotifyMessage>();

            // Register for the message 
            Messenger.Default.Register<NotifyListMessage>(this, this.OnNotifyListMessage);
        }

        #endregion

        #region Members

        /// <summary>
        /// Gets or sets the messages to be displayed in a view
        /// </summary>
        public IEnumerable<NotifyMessage> Messages
        {
            get
            {
                var filteredMessages = from message in messages where CheckMessage(message) select message;
                return filteredMessages;
            }
            set
            {
                messages = value;
                RaisePropertyChanged(() => Messages);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the <see cref="NotifyType.Info"/> messages are displayed
        /// </summary>
        public bool IsInfoSelected
        {
            get
            {
                return isInfoSelected;
            }
            set
            {
                isInfoSelected = value;
                RaisePropertyChanged(() => Messages);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the <see cref="NotifyType.Warning"/> messages are displayed
        /// </summary>
        public bool IsWarningsSelected
        {
            get
            {
                return isWarningsSelected;
            }
            set
            {
                isWarningsSelected = value;
                RaisePropertyChanged(() => Messages);
            }
        }

        /// <summary>
        /// Gets or sets a value indicating whether the <see cref="NotifyType.Error"/> messages are displayed
        /// </summary>
        public bool IsErrorsSelected
        {
            get
            {
                return isErrorsSelected;
            }
            set
            {
                isErrorsSelected = value;
                RaisePropertyChanged(() => Messages);
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// Handler of the <see cref="NotifyListMessage"/>. Grabs the messages to be 
        /// displayed and pass it to the <see cref="Messages"/>
        /// </summary>
        /// <param name="notifyListMessage"></param>
        private void OnNotifyListMessage(NotifyListMessage notifyListMessage)
        {
            this.Messages = notifyListMessage.Messages;
        }

        /// <summary>
        /// Check if the <see cref="NotifyMessage"/> should be displayed beside the <see cref="Messages"/>.
        /// Generally pass the internal filter parameters <see cref="isErrorsSelected"/>, <see cref="isInfoSelected"/>
        /// and <see cref="isWarningsSelected"/>
        /// </summary>
        /// <param name="message"><see cref="NotifyMessage"/> to check</param>
        /// <returns>True, if the message should be displayed, False otherwise</returns>
        private bool CheckMessage(NotifyMessage message)
        {
            return CheckMessage(message, isErrorsSelected, isInfoSelected, isWarningsSelected);
        }

        /// <summary>
        /// Check if the <see cref="NotifyMessage"/> should be displayed beside the <see cref="Messages"/>
        /// </summary>
        /// <param name="message"><see cref="NotifyMessage"/> to check</param>
        /// <param name="isError">Errors should be selected</param>
        /// <param name="isInfo">Info should be selected</param>
        /// <param name="isWarning">Warnings should be selected</param>
        /// <returns>True, if the message should be displayed, False otherwise</returns>
        #if DEBUG 
        public
        #else
        private
        #endif
        bool CheckMessage(NotifyMessage message, bool isError, bool isInfo, bool isWarning)
        {
            switch (message.Type)
            {
                case NotifyType.Error:
                    if (isError) return true;
                    return false;
                case NotifyType.Info:
                    if (isInfo) return true;
                    return false;
                case NotifyType.Warning:
                    if (isWarning) return true;
                    return false;
                default:
                    return false;
            }
        }

        #endregion
    }
}
